package tech.heiming.aps.scheduler.deadline;

import lombok.extern.slf4j.Slf4j;
import org.optaplanner.core.api.solver.SolverJob;
import org.optaplanner.core.api.solver.SolverManager;
import org.optaplanner.core.api.solver.SolverStatus;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.UUID;
import java.util.concurrent.ExecutionException;

/**
 * @author heimingz
 */
@Slf4j
@Component
public class DeadlineFirstScheduler {
    private final SolverManager<ScheduleTable, UUID> solverManager;

    @Autowired
    public DeadlineFirstScheduler(SolverManager<ScheduleTable, UUID> solverManager) {
        this.solverManager = solverManager;
    }

    public ScheduleTable solveAndWait(UUID problemId, ScheduleTable scheduleTable) {
        SolverJob<ScheduleTable, UUID> solverJob = solverManager.solve(problemId, scheduleTable);
        ScheduleTable solution;
        try {
            // Wait until the solving ends
            solution = solverJob.getFinalBestSolution();
        } catch (InterruptedException | ExecutionException e) {
            throw new IllegalStateException("Solving failed.", e);
        }
        return solution;
    }

    public void solveAndSave(UUID problemId, ScheduleTable scheduleTable) {
        SolverJob<ScheduleTable, UUID> solverJob = solverManager
                .solveAndListen(problemId, uuid -> scheduleTable, this::save);
    }

    public SolverStatus getSolverStatus(UUID timeTableId) {
        return solverManager.getSolverStatus(timeTableId);
    }

    public void terminateEarly(UUID timeTableId) {
        solverManager.terminateEarly(timeTableId);
    }

    private ScheduleTable getScheduleTable(UUID uuid) {
        return null;
    }

    private void save(ScheduleTable scheduleTable) {
        log.error(scheduleTable.toString());
    }
}
